grammar RichRail;

@lexer::header {
	package com.richrail.console.dsl;
}
@parser::header {
	package com.richrail.console.dsl;
	
	import com.richrail.console.commands.*;
	import com.richrail.model.entities.DepotStorage;
}
@parser::members {
	// Just make it public, getter and setter in this case is
	// nothing more than a glorified public member.
	public String response;
	
	// We should only have one instance of each command in this case.
	// Why not making them singletons? Because this works just fine.
	// No need to use the Singleton pattern unless it is really necessary,
	// because it also has a lot of drawbacks.
	private static NewTrainCommand newTrainCommand = new NewTrainCommand();
	private static NewWagonCommand newWagonCommand = new NewWagonCommand();
	private static AddCommand addCommand = new AddCommand();
	private static GetNumSeatsCommand getNumSeatsCommand = new GetNumSeatsCommand();
	private static DeleteCommand deleteCommand = new DeleteCommand();
	private static RemoveCommand removeCommand = new RemoveCommand();
	
	public static void setDepotStorage(DepotStorage depotStorage)
	{
		newTrainCommand.setDepotStorage(depotStorage);
		newWagonCommand.setDepotStorage(depotStorage);
		addCommand.setDepotStorage(depotStorage);
		getNumSeatsCommand.setDepotStorage(depotStorage);
		deleteCommand.setDepotStorage(depotStorage);
		removeCommand.setDepotStorage(depotStorage);
	}
}

/*------------------------------------------------------------------
 * PARSER RULES
 *------------------------------------------------------------------*/

command:
	(newcommand | addcommand | getcommand | delcommand | remcommand) ';'?
	;
newcommand:
	newtraincommand | newwagoncommand
	;
newtraincommand:
	'new' 'train' ID?
	{ response = newTrainCommand.execute($ID.text); }
	;
newwagoncommand:
	'new' 'wagon' ID? ('numseats' NUMBER)?
	{ response = newWagonCommand.execute($ID.text, $NUMBER.text != null ? new Integer(Integer.parseInt($NUMBER.text)) : null); }
	;
addcommand:
	'add' add=ID 'to' to=ID
	{ response = addCommand.execute($add.text, $to.text); }
	;
getcommand:
	'getnumseats' type ID
	{ response = getNumSeatsCommand.execute($type.text, $ID.text); }
	;
delcommand:
	'delete' type ID
	{ response = deleteCommand.execute($type.text, $ID.text); }
	;
remcommand:
	'remove' remove=ID 'from' from=ID
	{ response = removeCommand.execute($remove.text, $from.text); }
	;
type:
	'train' | 'wagon'
	;

/*------------------------------------------------------------------
 * LEXER RULES
 *------------------------------------------------------------------*/

ID:		('a'..'z') ('a'..'z'|'0'..'9')*;
NUMBER:		'0'..'9'+;
WS:		('\t'|' '|'\r'|'\n'|'\u000C')+	{ $channel = HIDDEN; };